package com.lcn.zk;

import com.lcn.pojo.netty.NettyServerNode;
import com.lcn.utils.JsonUtils;
import com.lcn.utils.RedisOperator;
import jakarta.annotation.Resource;
import lombok.Data;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.CuratorWatcher;
import org.apache.curator.framework.recipes.cache.CuratorCache;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "zookeeper.curator")
public class CuratorConfig {

    private String host; // 单节点/集群主机
    private String namespace; // 命名空间(根节点)
    private Integer connectionTimeoutMs; // 连接超时时间
    private Integer sessionTimeoutMs; // 会话超时时间
    private Integer baseSleepTimeMs; // 每次重试间隔时间
    private Integer maxRetires; // 最大重试次数

    public static final String PATH = "/server-list";

    @Resource
    private RedisOperator redis;

    @Resource
    private RabbitAdmin rabbitAdmin;

    @Bean("curatorClient")
    public CuratorFramework curatorClient() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(baseSleepTimeMs, maxRetires);
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(host)
                .connectionTimeoutMs(connectionTimeoutMs)
                .sessionTimeoutMs(sessionTimeoutMs)
                .retryPolicy(retryPolicy)
                .namespace(namespace)
                .build();
        client.start(); // 启动client客户端
        addWatcher(PATH, client);
        return client;
    }

    /**
     * 添加事件监听器
     *
     * @param path
     * @param client
     */
    public void addWatcher(String path, CuratorFramework client) {
        CuratorCache curatorCache = CuratorCache.build(client, path);
        // type:事件类型、oldData:旧数据、newData:新数据
        curatorCache.listenable().addListener((type, oldData, newData) -> {
            switch (type) {
                case NODE_CREATED -> {
                    System.out.println("------>zk创建事件");
                }
                case NODE_CHANGED -> {
                    System.out.println("------>zk修改事件");
                }
                case NODE_DELETED -> {
                    // 获取旧事件，删除端口号
                    System.out.println("------>zk删除事件");
                    NettyServerNode nettyServerNode = JsonUtils.jsonToPojo(new String(oldData.getData()), NettyServerNode.class);
                    String port = String.valueOf(nettyServerNode.getPort());
                    redis.hdel("netty_port", port);
                    // 删除旧的MQ队列
                    String queueName = "netty_queue_" + port;
                    rabbitAdmin.deleteQueue(queueName);
                }
                default -> {
                    System.out.println("zk无效事件");
                }
            }
        });
        curatorCache.start();
    }

}
